package aino;

import aino.*;
import java.io.*;
import java.util.*;


public class Method {
    int accessFlags;
    int nameIndex;
    int descriptorIndex;
    int attributesCount;
    Attribute[] attributes;
    int args;
    Vector calls;
    int firstAddr;
    int lastAddr;
    Class cls;

    public Method(Class cl, int af, int ni, int di, int ac) {
	cls = cl;
	accessFlags = af;
	nameIndex = ni;
	descriptorIndex = di;
	attributesCount = ac;
	attributes = new Attribute[ac];
	calls = new Vector();
    }

    public void addAttribute(int i, Attribute a) {
	attributes[i] = a;
    }

    public String getMethodName() {
	return Aino.fixStr(cls.name)+"_"+
	    Aino.fixStr(cls.getConst(nameIndex))+
	    Aino.fixStr(cls.getConst(descriptorIndex));
    }

    public int getLineNumber(int pc) {
	return attributes[0].getLineNumber(pc);
    }

    public int getMaxStack() {
	return attributes[0].getMaxStack();
    }

    public int getMaxLocals() {
	return attributes[0].getMaxLocals();
    }

    public int getCodeLength() {
	return attributes[0].getCodeLength();
    }

    public int getCodeByte(int i) {
	return attributes[0].getCodeByte(i);
    }

    public byte getCodeByte1(int i) {
	return attributes[0].getCodeByte1(i);
    }

    public int getCodeShort(int i) {
	int result;
	result = (attributes[0].getCodeByte(i)<<8)|
	    (attributes[0].getCodeByte(i+1));
	return result;
    }

    public int getSignCodeShort(int i) {
	int result;
	result = (attributes[0].getSignCodeByte(i)<<8)|
	    (attributes[0].getCodeByte(i+1));
	return result;
    }

    public short getCodeShort1(int i) {
	int result;
	result = getCodeByte1(i);
	result = result<<8;
	result = result | getCodeByte1(i+1);
	return (short)result;
    }

    public int getCodeInt(int i) {
	return (attributes[0].getCodeByte(i)<<24)|
	    (attributes[0].getCodeByte(i+1)<<16)|
	    (attributes[0].getCodeByte(i+2)<<8)|
	    attributes[0].getCodeByte(i+3);
    }

    public int getSignCodeInt(int i) {
	return (attributes[0].getSignCodeByte(i)<<24)|
	    (attributes[0].getCodeByte(i+1)<<16)|
	    (attributes[0].getCodeByte(i+2)<<8)|
	    attributes[0].getCodeByte(i+3);
    }

    public int getNextPC(int pc) {
	int code = getCodeByte(pc);
	int len = Integer.decode(codeTable[code][1]).intValue();
	if (len > 0) return pc + len;
	if (code == 0xaa) { // tableswitch
	    pc++;
	    while ((pc % 4) != 0) pc++;
	    int low = (getCodeByte(pc+4)<<24)|(getCodeByte(pc+5)<<16)|
		(getCodeByte(pc+6)<<8)|getCodeByte(pc+7);
	    int high = (getCodeByte(pc+8)<<24)|(getCodeByte(pc+9)<<16)|
		(getCodeByte(pc+10)<<8)|getCodeByte(pc+11);
	    return pc + 12 + (high - low + 1)*4;
	} else 	if (code == 0xab) { // lookupswitch
	    pc++;
	    while ((pc % 4) != 0) pc++;
	    int npairs = (getCodeByte(pc+4)<<24)|(getCodeByte(pc+5)<<16)|
		(getCodeByte(pc+6)<<8)|getCodeByte(pc+7);
	    return pc + 8 + 8*npairs;
	}
	System.out.println("\n*** Internal error!");
	System.exit(1);
	return 0;
    }

   static String[][] codeTable = {
       {"0x00", "1", "nop"},
       {"0x01", "1", "aconst_null"},
       {"0x02", "1", "iconst_m1"},
       {"0x03", "1", "iconst_0"},
       {"0x04", "1", "iconst_1"},
       {"0x05", "1", "iconst_2"},
       {"0x06", "1", "iconst_3"},
       {"0x07", "1", "iconst_4"},
       {"0x08", "1", "iconst_5"},
       {"0x09", "1", "lconst_0"},
       {"0x0a", "1", "lconst_1"},
       {"0x0b", "1", "fconst_0"},
       {"0x0c", "1", "fconst_1"},
       {"0x0d", "1", "fconst_2"},
       {"0x0e", "1", "dconst_0"},
       {"0x0f", "1", "dconst_1"},
       {"0x10", "2", "bipush"},
       {"0x11", "3", "sipush"},
       {"0x12", "2", "ldc"},
       {"0x13", "3", "ldc_w"},
       {"0x14", "3", "ldc2_w"},
       {"0x15", "2", "iload"},
       {"0x16", "2", "lload"},
       {"0x17", "2", "fload"},
       {"0x18", "2", "dload"},
       {"0x19", "2", "aload"},
       {"0x1a", "1", "iload_0"},
       {"0x1b", "1", "iload_1"},
       {"0x1c", "1", "iload_2"},
       {"0x1d", "1", "iload_3"},
       {"0x1e", "1", "lload_0"},
       {"0x1f", "1", "lload_1"},
       {"0x20", "1", "lload_2"},
       {"0x21", "1", "lload_3"},
       {"0x22", "1", "fload_0"},
       {"0x23", "1", "fload_1"},
       {"0x24", "1", "fload_2"},
       {"0x25", "1", "fload_3"},
       {"0x26", "1", "dload_0"},
       {"0x27", "1", "dload_1"},
       {"0x28", "1", "dload_2"},
       {"0x29", "1", "dload_3"},
       {"0x2a", "1", "aload_0"},
       {"0x2b", "1", "aload_1"},
       {"0x2c", "1", "aload_2"},
       {"0x2d", "1", "aload_3"},
       {"0x2e", "1", "iaload"},
       {"0x2f", "1", "laload"},
       {"0x30", "1", "faload"},
       {"0x31", "1", "daload"},
       {"0x32", "1", "aaload"},
       {"0x33", "1", "baload"},
       {"0x34", "1", "caload"},
       {"0x35", "1", "saload"},
       {"0x36", "2", "istore"},
       {"0x37", "2", "lstore"},
       {"0x38", "2", "fstore"},
       {"0x39", "2", "dstore"},
       {"0x3a", "2", "astore"},
       {"0x3b", "1", "istore_0"},
       {"0x3c", "1", "istore_1"},
       {"0x3d", "1", "istore_2"},
       {"0x3e", "1", "istore_3"},
       {"0x3f", "1", "lstore_0"},
       {"0x40", "1", "lstore_1"},
       {"0x41", "1", "lstore_2"},
       {"0x42", "1", "lstore_3"},
       {"0x43", "1", "fstore_0"},
       {"0x44", "1", "fstore_1"},
       {"0x45", "1", "fstore_2"},
       {"0x46", "1", "fstore_3"},
       {"0x47", "1", "dstore_0"},
       {"0x48", "1", "dstore_1"},
       {"0x49", "1", "dstore_2"},
       {"0x4a", "1", "dstore_3"},
       {"0x4b", "1", "astore_0"},
       {"0x4c", "1", "astore_1"},
       {"0x4d", "1", "astore_2"},
       {"0x4e", "1", "astore_3"},
       {"0x4f", "1", "iastore"},
       {"0x50", "1", "lastore"},
       {"0x51", "1", "fastore"},
       {"0x52", "1", "dastore"},
       {"0x53", "1", "aastore"},
       {"0x54", "1", "bastore"},
       {"0x55", "1", "castore"},
       {"0x56", "1", "sastore"},
       {"0x57", "1", "pop"},
       {"0x58", "1", "pop2"},
       {"0x59", "1", "dup"},
       {"0x5a", "1", "dup_x1"},
       {"0x5b", "1", "dup_x2"},
       {"0x5c", "1", "dup2"},
       {"0x5d", "1", "dup2_x1"},
       {"0x5e", "1", "dup2_x2"},
       {"0x5f", "1", "swap"},
       {"0x60", "1", "iadd"},
       {"0x61", "1", "ladd"},
       {"0x62", "1", "fadd"},
       {"0x63", "1", "dadd"},
       {"0x64", "1", "isub"},
       {"0x65", "1", "lsub"},
       {"0x66", "1", "fsub"},
       {"0x67", "1", "dsub"},
       {"0x68", "1", "imul"},
       {"0x69", "1", "lmul"},
       {"0x6a", "1", "fmul"},
       {"0x6b", "1", "dmul"},
       {"0x6c", "1", "idiv"},
       {"0x6d", "1", "ldiv"},
       {"0x6e", "1", "fdiv"},
       {"0x6f", "1", "ddiv"},
       {"0x70", "1", "irem"},
       {"0x71", "1", "lrem"},
       {"0x72", "1", "frem"},
       {"0x73", "1", "drem"},
       {"0x74", "1", "ineg"},
       {"0x75", "1", "lneg"},
       {"0x76", "1", "fneg"},
       {"0x77", "1", "dneg"},
       {"0x78", "1", "ishl"},
       {"0x79", "1", "lshl"},
       {"0x7a", "1", "ishr"},
       {"0x7b", "1", "lshr"},
       {"0x7c", "1", "iushr"},
       {"0x7d", "1", "lushr"},
       {"0x7e", "1", "iand"},
       {"0x7f", "1", "land"},
       {"0x80", "1", "ior"},
       {"0x81", "1", "lor"},
       {"0x82", "1", "ixor"},
       {"0x83", "1", "lxor"},
       {"0x84", "3", "iinc"},
       {"0x85", "1", "i2l"},
       {"0x86", "1", "i2f"},
       {"0x87", "1", "i2d"},
       {"0x88", "1", "l2i"},
       {"0x89", "1", "l2f"},
       {"0x8a", "1", "l2d"},
       {"0x8b", "1", "f2i"},
       {"0x8c", "1", "f2l"},
       {"0x8d", "1", "f2d"},
       {"0x8e", "1", "d2i"},
       {"0x8f", "1", "d2l"},
       {"0x90", "1", "d2f"},
       {"0x91", "1", "i2b"},
       {"0x92", "1", "i2c"},
       {"0x93", "1", "i2s"},
       {"0x94", "1", "lcmp"},
       {"0x95", "1", "fcmpl"},
       {"0x96", "1", "fcmpg"},
       {"0x97", "1", "dcmpl"},
       {"0x98", "1", "dcmpg"},
       {"0x99", "3", "ifeq"},
       {"0x9a", "3", "ifne"},
       {"0x9b", "3", "iflt"},
       {"0x9c", "3", "ifge"},
       {"0x9d", "3", "ifgt"},
       {"0x9e", "3", "ifle"},
       {"0x9f", "3", "if_icmpeq"},
       {"0xa0", "3", "if_icmpne"},
       {"0xa1", "3", "if_icmplt"},
       {"0xa2", "3", "if_icmpge"},
       {"0xa3", "3", "if_icmpgt"},
       {"0xa4", "3", "if_icmple"},
       {"0xa5", "3", "if_acmpeq"},
       {"0xa6", "3", "if_acmpne"},
       {"0xa7", "3", "goto"},
       {"0xa8", "3", "jsr"},
       {"0xa9", "2", "ret"},
       {"0xaa", "0", "tableswitch"},
       {"0xab", "0", "lookupswitch"},
       {"0xac", "1", "ireturn"},
       {"0xad", "1", "lreturn"},
       {"0xae", "1", "freturn"},
       {"0xaf", "1", "dreturn"},
       {"0xb0", "1", "areturn"},
       {"0xb1", "1", "return"},
       {"0xb2", "3", "getstatic"},
       {"0xb3", "3", "putstatic"},
       {"0xb4", "3", "getfield"},
       {"0xb5", "3", "putfield"},
       {"0xb6", "3", "invokevirtual"},
       {"0xb7", "3", "invokespecial"},
       {"0xb8", "3", "invokestatic"},
       {"0xb9", "5", "invokeinterface"},
       {"0xba", "1", "xxxunusedxxx"},
       {"0xbb", "3", "new"},
       {"0xbc", "2", "newarray"},
       {"0xbd", "3", "anewarray"},
       {"0xbe", "1", "arraylength"},
       {"0xbf", "1", "athrow"},
       {"0xc0", "3", "checkcast"},
       {"0xc1", "3", "instanceof"},
       {"0xc2", "1", "monitorenter"},
       {"0xc3", "1", "monitorexit"},
       {"0xc4", "4", "wide"},
       {"0xc5", "4", "multianewarray"},
       {"0xc6", "3", "ifnull"},
       {"0xc7", "3", "ifnonnull"},
       {"0xc8", "5", "goto_w"},
       {"0xc9", "5", "jsr_w"},
       {"0xca", "1", "breakpoint"},
       {"0xcb", "1", "xxxunusedxxx"},
       {"0xcc", "1", "xxxunusedxxx"},
       {"0xcd", "1", "xxxunusedxxx"},
       {"0xce", "1", "xxxunusedxxx"},
       {"0xcf", "1", "xxxunusedxxx"},
       {"0xd0", "1", "xxxunusedxxx"},
       {"0xd1", "1", "xxxunusedxxx"},
       {"0xd2", "1", "xxxunusedxxx"},
       {"0xd3", "1", "xxxunusedxxx"},
       {"0xd4", "1", "xxxunusedxxx"},
       {"0xd5", "1", "xxxunusedxxx"},
       {"0xd6", "1", "xxxunusedxxx"},
       {"0xd7", "1", "xxxunusedxxx"},
       {"0xd8", "1", "xxxunusedxxx"},
       {"0xd9", "1", "xxxunusedxxx"},
       {"0xda", "1", "xxxunusedxxx"},
       {"0xdb", "1", "xxxunusedxxx"},
       {"0xdc", "1", "xxxunusedxxx"},
       {"0xdd", "1", "xxxunusedxxx"},
       {"0xde", "1", "xxxunusedxxx"},
       {"0xdf", "1", "xxxunusedxxx"},
       {"0xe0", "1", "xxxunusedxxx"},
       {"0xe1", "1", "xxxunusedxxx"},
       {"0xe2", "1", "xxxunusedxxx"},
       {"0xe3", "1", "xxxunusedxxx"},
       {"0xe4", "1", "xxxunusedxxx"},
       {"0xe5", "1", "xxxunusedxxx"},
       {"0xe6", "1", "xxxunusedxxx"},
       {"0xe7", "1", "xxxunusedxxx"},
       {"0xe8", "1", "xxxunusedxxx"},
       {"0xe9", "1", "xxxunusedxxx"},
       {"0xea", "1", "xxxunusedxxx"},
       {"0xeb", "1", "xxxunusedxxx"},
       {"0xec", "1", "xxxunusedxxx"},
       {"0xed", "1", "xxxunusedxxx"},
       {"0xee", "1", "xxxunusedxxx"},
       {"0xef", "1", "xxxunusedxxx"},
       {"0xf0", "1", "xxxunusedxxx"},
       {"0xf1", "1", "xxxunusedxxx"},
       {"0xf2", "1", "xxxunusedxxx"},
       {"0xf3", "1", "xxxunusedxxx"},
       {"0xf4", "1", "xxxunusedxxx"},
       {"0xf5", "1", "xxxunusedxxx"},
       {"0xf6", "1", "xxxunusedxxx"},
       {"0xf7", "1", "xxxunusedxxx"},
       {"0xf8", "1", "xxxunusedxxx"},
       {"0xf9", "1", "xxxunusedxxx"},
       {"0xfa", "1", "xxxunusedxxx"},
       {"0xfb", "1", "xxxunusedxxx"},
       {"0xfc", "1", "xxxunusedxxx"},
       {"0xfd", "1", "xxxunusedxxx"},
       {"0xfe", "1", "impdep1"},
       {"0xff", "1", "impdep2"},
   };

    void printCodes() {
	int i = 0;
	int len = getCodeLength();
	while (i < len) {
	    int c = getCodeByte(i);
	    if (c < 0) c += 256;
	    System.out.println(codeTable[c][2]);
	    i += Integer.decode(codeTable[c][1]).intValue();
	}
    }

}

